// Copyright (C) joyinter
// All rights reserved.
// 
// Author : Jiang Li
// Date   : 2004-11-8

#include "stdafx.h"
#include "net_send.h"
#include "net_socket.h"
#include "net_monitor.h"

namespace JoyServer
{

// class CJoySendOverlapped

CJoySendOverlapped::CJoySendOverlapped(
    CJoySockData* sockData, CJoyTransmitData* sendData):
    CJoyOverlapped(sockData), m_sendData(sendData)
{
    m_sendData->AddRef();
    ++ m_sockData->m_sendCount;
}

CJoySendOverlapped::~CJoySendOverlapped()
{
    -- m_sockData->m_sendCount;
#ifdef JOY_ENABLE_NET_MONITOR
    int s = m_sendData->m_buf.GetSize();
    if(m_sockData->m_bStream)
    {
        g_netMonitor.AddSend(m_sockData->m_handle, s);
    }
    else
    {
        g_netMonitor.AddSendTo(m_sockData->m_handle, s);
    }
#endif
    m_sendData->Release();
}

// class CJoySocket

bool CJoySocket::Send(CJoyTransmitData* sendData, int& err)
{
    err = 0;

    if(m_sockData == NULL)
    {
        return false;
    }

    DWORD dwSent = 0;
    WSABUF buf;
    buf.buf = (char*)sendData->m_buf.GetBuffer();
    buf.len = sendData->m_buf.GetSize();

    CJoySendOverlapped* pOverlapped =
        new CJoySendOverlapped(m_sockData, sendData);
    
    if(SOCKET_ERROR == ::WSASend(
        m_sockData->m_handle,
        &buf, 1, &dwSent, 0,
        pOverlapped->ToOsOverlapped(),
        NULL))
    {
        int e = WSAGetLastError();
        if(e != WSA_IO_PENDING)
        {
            err = e;
            delete pOverlapped;
            return false;
        }
    }

    return false;
}

bool CJoySocket::Send(CJoyTransmitData* sendData)
{
    int err = 0;
    return Send(sendData, err);
}

bool CJoySocket::Send(const void* buf, int len, int& err)
{
    CJoyTransmitData* data = new CJoyTransmitData(buf, len);
    bool b = Send(data, err);
    data->Release();
    return b;
}

bool CJoySocket::Send(const void* buf, int len)
{
    int err = 0;
    return Send(buf, len, err);
}

bool CJoySocket::SendTo(CJoyTransmitData* sendData, const sockaddr_in& addr, int& err)
{
    err = 0;

    if(m_sockData == NULL)
    {
        return false;
    }

    DWORD dwSent = 0;
    WSABUF buf;
    buf.buf = (char*)sendData->m_buf.GetBuffer();
    buf.len = sendData->m_buf.GetSize();

    CJoySendOverlapped* pOverlapped =
        new CJoySendOverlapped(m_sockData, sendData);
    
    if(SOCKET_ERROR == ::WSASendTo(
        m_sockData->m_handle,
        &buf, 1, &dwSent, 0,
        (sockaddr*)&addr,
        sizeof(addr),
        pOverlapped->ToOsOverlapped(),
        NULL))
    {
        int e = WSAGetLastError();
        if(e != WSA_IO_PENDING)
        {
            err = e;
            delete pOverlapped;
            return false;
        }
    }

    return true;
}

bool CJoySocket::SendTo(CJoyTransmitData* sendData, const sockaddr_in& addr)
{
    int err = 0;
    return SendTo(sendData, addr, err);
}

} // namespace JoyServer